#ifndef MOLECULE_DRAWER_HEADER_VIZMF_PROJECT
#define MOLECULE_DRAWER_HEADER_VIZMF_PROJECT

/*
  Molecule Drawers transform molecular representation into a set of 3D/2D primitives
  according to on of a set of representation styles.

*/

#include "src/core/workspace/molecule/molecule.h"
#include <string>
#include <vector>
#include <string>
#include "src/gui/itemwidget.h"
#include "src/core/scene/visitorparameters.h"
#include "src/core/scene/molecularvisitors.h"
// stub selections, needed while actual selections are being prepared...
struct SelectionTemp{};

struct AtomSelectionTemp : public SelectionTemp {
  typedef Molecule::atom_type* iterator;  // equivalent to Atom*
};
struct BondSelectionTemp : public SelectionTemp {
  typedef Molecule::bond_type* iterator;
};

class MoleculeDrawer {
public:
  typedef AtomSelectionTemp atom_selection_type;
  typedef BondSelectionTemp bond_selection_type;
  enum draw_type {wireframe = 0 , cpk, ballsandsticks, custom};

  MoleculeDrawer(const Molecule& mol, const VisitorParameters& params, draw_type dt=wireframe) : mol_(mol), draw_type_(dt), visitor_params(params) {}
  virtual ~MoleculeDrawer(){}

  void drawAll(ItemWidget* widget)
  {

    widget->startList(ItemWidget::Lit);
    CommonVisitor visitor(widget, visitor_params, std::string("CPK"));
    for (Molecule::atom_const_iterator i = mol_.atomsBegin(), e = mol_.atomsEnd(); i!=e; ++i)
    {
      visitor.drawAtom(i->coords(), i->element(), "");
    }
    for (Molecule::bond_const_iterator i = mol_.bondsBegin(), e = mol_.bondsEnd(); i!=e; ++i)
    {
      visitor.drawBond(i->from()->coords(), i->to()->coords(), i->from()->element(), i->to()->element(), "", "", i->order());
    }
    widget->endList();
  }

  void drawAtoms(atom_selection_type as, MolecularVisitor* visitor){
    typedef atom_selection_type::iterator ASI;
//    for(ASI i = as.begin_atoms(), e = as.end_atoms(); i!=e; i++){
//      visitor->drawAtom(i->coords(), i->element(), i->atomType());
   // visitor->drawAtom(*i); // as an alternative, i.e. based on void MoleculeVisitor::drawAtom(Atom& at);
//    }
  };

  void drawBonds(bond_selection_type bs, MolecularVisitor* visitor){
    typedef bond_selection_type::iterator BSI;
//    for(BSI i = bs.begin_atoms(), e = bs.end_atoms(); i!=e; i++){
//      visitor->drawBond(i->from()->coords(), i->to()->coords(), i->from()->element(), i->to()->element(),
//                        i->from()->atomType(), i->to()->atomType(), i->order());
   // visitor->drawBond(*i); // as an alternative, i.e. based on void MoleculeVisitor::drawBond(Molecule::bond_type& bond);
//    }
  };

protected:
  const Molecule& mol_;
  draw_type draw_type_;
  const VisitorParameters& visitor_params;
};

#endif // MOLECULE_DRAWER_HEADER_VIZMF_PROJECT
